using System.Collections.Generic;
using System.Globalization;
#if ODIN_INSPECTOR
using Sirenix.OdinInspector;
#endif
using UnityEngine;

namespace JH
{
    /// <summary>
    ///  分割线渲染器基类
    /// </summary>
    public class BasicDividingLineRender : BasicMonoRender<Vector2>
    {
        /// <summary>
        /// 需要隐藏的分割线索引
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("需要隐藏的分割线索引")]
#endif
        private int[] hideDividingLines;

        /// <summary>
        /// 需要隐藏的标签索引
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("需要隐藏的标签索引")]
#endif
        private int[] hideDividingLabels;

        /// <summary>
        ///  左（或下）分割线预制体
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("左（或下）分割线预制体")]
#endif
        private BasicDivisionLine leftOrBottomLinePrefab;

        /// <summary>
        ///  中间分割线预制体
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("中间分割线预制体")]
#endif
        private BasicDivisionLine middleDividingLinePrefab;

        /// <summary>
        ///  右（或上）分割线预制体
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("右（或上）分割线预制体")]
#endif
        private BasicDivisionLine rightOrTopLinePrefab;

        /// <summary>
        ///  分割线的数量
        /// </summary>
        [SerializeField]
#if ODIN_INSPECTOR
        [LabelText("分割线数量")]
#endif
        private int splitCount = 3;

        /// <summary>
        ///  分割线实例
        /// </summary>
        private List<BasicDivisionLine> _dividingLines = new();

        /// <summary>
        ///  分割线的对象池
        /// </summary>
        private Dictionary<DivisionLineType, Stack<BasicDivisionLine>> _pool = new();

        /// <summary>
        ///  图表的边界处理器
        /// </summary>
        [SerializeField] [HideInInspector] private BoundaryHandler boundaryHandler;

        /// <summary>
        /// 是否是水平分割线
        /// </summary>
        protected virtual bool IsHorizontal => true;

        public override void Render()
        {
            if (boundaryHandler == null || !Application.isPlaying) return;

            // 渲染分割线
            RenderSplitLines();
        }

        /// <summary>
        ///  渲染分割线
        /// </summary>
        private void RenderSplitLines()
        {
            //清空上一次的分割线
            ClearLastSplitLines();

            // 如果不展示分割线，直接返回
            if (splitCount <= 0) return;

            //重新计算新得分割线
            ReCalcNewSplitLines();

            //根据不渲染集合的索引进行隐藏
            SetHiddenDividingLinesAndLabels();
        }

        /// <summary>
        ///  根据不渲染集合的索引进行隐藏标签和分割线
        /// </summary>
        private void SetHiddenDividingLinesAndLabels()
        {
            for (var index = 0; index < _dividingLines.Count; index++)
            {
                var each = _dividingLines[index];

                // 判定标签是否需要显示隐藏
                each.ShowLabel = IsNeedShowLabel(index);

                // 判定分割线是否需要显示隐藏
                each.ShowLine = IsNeedShowLine(index);
            }
        }

        /// <summary>
        ///  判定是否需要显示分割线
        /// </summary>
        private bool IsNeedShowLine(int index)
        {
            bool needShowLine = true;
            for (int i = 0; i < hideDividingLines.Length; i++)
            {
                if (hideDividingLines[i] == index)
                {
                    needShowLine = false;
                    break;
                }
            }

            return needShowLine;
        }

        /// <summary>
        ///  判定是否需要显示标签
        /// </summary>
        private bool IsNeedShowLabel(int index)
        {
            bool needShowLabel = true;
            for (int i = 0; i < hideDividingLabels.Length; i++)
            {
                if (hideDividingLabels[i] == index)
                {
                    needShowLabel = false;
                    break;
                }
            }

            return needShowLabel;
        }

        /// <summary>
        /// 重新计算新得分割线
        /// </summary>
        private void ReCalcNewSplitLines()
        {
            // 从最小值开始向上递增
            for (int i = 0; i < splitCount; i++)
            {
                // 获取预制体
                var prefab = i == 0 ? leftOrBottomLinePrefab :
                    i == splitCount - 1 ? rightOrTopLinePrefab : middleDividingLinePrefab;
                if (!prefab) continue;

                // 计算分割线对应的值
                var value = GetLineValue(i);

                // 获取一个分割线
                var each = Get(prefab);
                each.Value = value;
                
                // 添加到分割线集合中
                _dividingLines.Add(each);
            }
        }

        /// <summary>
        ///  获取分割线对应的值
        /// </summary>
        private float GetLineValue(int index)
        {
            // 获取范围
            var range = IsHorizontal ? boundaryHandler.YRange : boundaryHandler.XRange;

            // 计算长度
            var length = range.y - range.x;

            // 计算单个分割线的间隔
            var splitInterval = length / (splitCount - 1);

            // 计算分割线对应的值
            return splitInterval * index + range.x;
        }

        /// <summary>
        /// 清空上一次的分割线
        /// </summary>
        private void ClearLastSplitLines()
        {
            //回收分割线
            var children = GetComponentsInChildren<BasicDivisionLine>();

            // 全部压到栈中，不再持有
            for (var i = 0; i < children.Length; i++)
            {
                var each = children[i];
                // 设置分割线和标签不可见
                each.ShowLine = each.ShowLabel = false;

                each.ShowLine = each.ShowLabel = false;
                if (_pool.TryGetValue(each.divisionLineType, out var stack))
                {
                    stack.Push(each);
                }
                else
                {
                    _pool[each.divisionLineType] = new Stack<BasicDivisionLine>();
                    _pool[each.divisionLineType].Push(each);
                }
            }

            // 清空集合
            _dividingLines.Clear();
        }

        /// <summary>
        ///  获取一个分割线
        /// </summary>
        private BasicDivisionLine Get(BasicDivisionLine prefab)
        {
            if (_pool.TryGetValue(prefab.divisionLineType, out var stack) && stack.Count > 0)
            {
                return stack.Pop();
            }

            var ret = Instantiate(prefab.gameObject, transform).GetComponent<BasicDivisionLine>();

            // 设置边界处理器
            ret.BoundaryHandler = boundaryHandler;

            return ret;
        }

        protected override void OnValidate()
        {
            base.OnValidate();
            Priority = 1;
            splitCount = Mathf.Max(0, splitCount);
            boundaryHandler = this.GetChartComp<BoundaryHandler, Vector2>();
        }
    }
}